
#ifndef C_MQTT_MQTT_H
#define C_MQTT_MQTT_H

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned char bool;

#define false 0
#define true 1

//MQTT协议版本 3.3.1
#define VERSION 0x04

//头部flag
#define FLAG_CONNECT 0
#define FLAG_CONNACK 0
#define FLAG_PUBLISH 0
#define FLAG_PUBACK 0
#define FLAG_PUBREC 0
#define FLAG_PUBREL 2
#define FLAG_PUBCOMP 0
#define FLAG_SUBSCRIBE 2
#define FLAG_SUBACK 0
#define FLAG_UNSUBSCRIBE 2
#define FLAG_UNSUBACK 0
#define FLAG_PINGREQ 0
#define FLAG_PINGRESP 0
#define FLAG_DISCONNECT 0

//ACK应答bit定义
#define FLAG_BIT_ACK_SUBSCRIBE 0
#define FLAG_BIT_ACK_UNSUBSCRIBE 1
#define FLAG_BIT_ACK_PUBLISH 2
#define FLAG_BIT_ACK_PUBREC 3
#define FLAG_BIT_ACK_PUBREL 4
#define FLAG_BIT_ACK_CONNECT 5

//发送缓存
#define SEND_BUF_MAX 128
//最大订阅topic数
#define SUB_TOPIC_MAX 2
#define ACK_TIMEOUT 8

//包类型
typedef enum {
    RESERVED = 0, //无权限 预留
    CONNECT, //客户端请求连接服务器
    CONNACK, //服务器连接应答
    PUBLISH, //双向 发布消息
    PUBACK, //双向 发布消息应答
    PUBREC, //双向 发布已收到-1
    PUBREL, //双向 发布版本-2
    PUBCOMP, //双向 发布完成-3
    SUBSCRIBE, //客户端请求订阅topic
    SUBACK, //服务端订阅应答
    UNSUBSCRIBE, //客户端取消订阅请求
    UNSUBACK, //取消订阅应答
    PINGREQ, //ping请求
    PINGRESP, //ping应答
    DISCONNECT, //断连请求
    RESERVEDS //无权限 预留

} PACKET_TYPE;

//MQTT回调函数
typedef struct {
    //连接成功
    void (*on_connect)(void);
    //收到消息（topic, 消息内容）
    void (*on_message)(char *, char *);
    //订阅成功
    void (*on_sub_success)(void);
    //出现错误（错误消息）
    void (*on_error)(char *);
    //断开连接
    void (*disconnect)(void);
} MQTT_CALLBACK;

//mqtt连接参数配置
typedef struct {
    char *host;
    u16 port;
    char *client_id;
    char *username;
    char *password;
    u16 keep_alive;
    u8 clean_session;
    u8 retain;
    MQTT_CALLBACK callback;
} MQTT_CONFIG;

typedef struct {
    char *topic;
    u8 qos;
} MQTT_SUBSCRIBE;

void mqtt_decode(u8 *buf, u16 len);
void mqtt_sys_tick_s(void);
bool mqtt_connect(MQTT_CONFIG *config, void (*net_tcp_send)(char *data_buf, u16 len), u8 (*net_tcp_connect)(char *host, u16 port));
void mqtt_publish_len(char *topic, char *msg, u8 qos, u8 retain);
void mqtt_publish(char *topic, u8 topic_len, char *msg, u16 len, u8 qos, u8 retain);
bool mqtt_subscribe(char *topic, u8 qos);
bool mqtt_unsubscribe(char *topic);
#endif